import java.io.IOException;
import java.util.ArrayList;

public class MySyntaxAnalyzer implements SyntaxAnalyzer {

	private MyLexicalAnalyzer lexer = new MyLexicalAnalyzer();
	static ArrayList<String> syntaxList = new ArrayList<String>();

	public void document() throws CompilerException, IOException {
		lexer.getNextToken();
		if (!Compiler.token.equalsIgnoreCase("#Start Document")) {
			String message = "A #Start Document annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}
		if (Compiler.token.equalsIgnoreCase("#START DOCUMENT")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			define();
			head();
			body();
			if (Compiler.token.equalsIgnoreCase("#END DOCUMENT")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
				Compiler.token = "";
			} else
				throw new IOException("NOT A LEGAL TAG!");
		}

		if (!Compiler.token.equalsIgnoreCase("#End Document")) {
			String message = "A #End Document annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}
	}

	public void body() throws CompilerException, IOException {
		innerText();
		body();
		if (Compiler.token.equalsIgnoreCase("#START PARAGRAPH")) {
			paragraph();
			body();
		}
		if (Compiler.token.equalsIgnoreCase("#START BOLD")) {
			bold();
			body();
		}
		if (Compiler.token.equalsIgnoreCase("#START ITALICS")) {
			italics();
			body();
		}
		if (Compiler.token.equalsIgnoreCase("#START LIST")) {
			list();
			body();
		} else {
			// do nothing
		}
	}

	public void head() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#START HEAD")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			title();
			if (Compiler.token.equalsIgnoreCase("#END HEAD")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else {
				String message = "A #End Head annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			}

		}

	}

	public void title() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#START TITLE")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			title();
			if (Compiler.token.equalsIgnoreCase("#END TITLE")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else  {
				String message = "A #End Title annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			}

		}

	}

	public void paragraph() throws CompilerException, IOException {
		if (!Compiler.token.equalsIgnoreCase("#Start Paragraph")) {
			String message = "A #Start Paragraph annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

		if (Compiler.token.equalsIgnoreCase("#START PARAGRAPH")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			define();
			innerParagraph();
			if (Compiler.token.equalsIgnoreCase("#END PARAGRAPH")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else
				throw new IOException("NOT A LEGAL TAG!");
		}

		if (!Compiler.token.equalsIgnoreCase("#End Paragraph")) {
			String message = "A #End Paragraph annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

	}

	public void bold() throws CompilerException, IOException {
		if (!Compiler.token.equalsIgnoreCase("#Start Bold")) {
			String message = "A #Start Bold annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

		if (Compiler.token.equalsIgnoreCase("#START BOLD")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			define();
			innerText();
			if (Compiler.token.equalsIgnoreCase("#END BOLD")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else
				throw new IOException("NOT A LEGAL TAG!");
		}

		if (!Compiler.token.equalsIgnoreCase("#End Bold")) {
			String message = "A #End Bold annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

	}

	public void italics() throws CompilerException, IOException {
		if (!Compiler.token.equalsIgnoreCase("#Start Italics")) {
			String message = "A #Start Italics annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

		if (Compiler.token.equalsIgnoreCase("#START ITALICS")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			define();
			innerText();
			if (Compiler.token.equalsIgnoreCase("#END ITALICS")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else
				throw new IOException("NOT A LEGAL TAG!");
		}

		if (!Compiler.token.equalsIgnoreCase("#End Italics")) {
			String message = "A #End Italics annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

	}

	public void list() throws CompilerException, IOException {
		if (!Compiler.token.equalsIgnoreCase("#Start List")) {
			String message = "A #Start List annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

		if (Compiler.token.equalsIgnoreCase("#START LIST")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			list();
			if (Compiler.token.equalsIgnoreCase("#END LIST")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else
				throw new IOException("NOT A LEGAL TAG!");
		}

		if (!Compiler.token.equalsIgnoreCase("#End List")) {
			String message = "A #End List annotation was expected when a "
					+ Compiler.token + "was found!";
			throw new CompilerException(message);
		}

	}

	public void item() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#START ITEM")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			define();
			innerList();
			if (Compiler.token.equalsIgnoreCase("#END ITEM")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
				item();
			} else {
				String message = "A #End Item annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			}
				
		}

		

	}

	public void audio() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#START AUDIO")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			text();
			if (Compiler.token.equalsIgnoreCase("#END AUDIO")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else {
				String message = "A #End Audio annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			}
				
		}

		

	}

	public void video() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#START VIDEO")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			text();
			if (Compiler.token.equalsIgnoreCase("#END VIDEO")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else if (!Compiler.token.equalsIgnoreCase("#End Video")) {
				String message = "A #End Video annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			}
				
		}

		

	}

	public void define() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#START DEFINE")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			if (Compiler.token.equalsIgnoreCase("#NAME")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
				text();
				if (Compiler.token.equalsIgnoreCase("VALUE")) {
					syntaxList.add(Compiler.token);
					lexer.getNextToken();
					text();
				}
			}
			if (Compiler.token.equalsIgnoreCase("#END DEFINE")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
				define();
			} else if (!Compiler.token.equalsIgnoreCase("#End Define")) {
				String message = "A #End Define annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			} 
				
		}


	}

	public void use() throws IOException, CompilerException {
		if (Compiler.token.equalsIgnoreCase("#START USE")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			text();
			if (Compiler.token.equalsIgnoreCase("#END USE")) {
				syntaxList.add(Compiler.token);
				lexer.getNextToken();
			} else {
				String message = "A #End Use annotation was expected when a "
						+ Compiler.token + "was found!";
				throw new CompilerException(message);
			} 
				
		}



	}

	public void innerParagraph() throws CompilerException, IOException {
		innerText();
		innerParagraph();
		if (Compiler.token.equalsIgnoreCase("#START BOLD")) {
			bold();
			innerParagraph();
		}
		if (Compiler.token.equalsIgnoreCase("#START ITALICS")) {
			italics();
			innerParagraph();
		}
		if (Compiler.token.equalsIgnoreCase("#START LIST")) {
			list();
			innerParagraph();
		}
		if (Compiler.token.equalsIgnoreCase("#NEWLINE")) {
			newLine();
			innerParagraph();
		} else {
			// do nothing
		}
	}

	public void newLine() throws CompilerException, IOException {
		if (Compiler.token.equalsIgnoreCase("#NEWLINE")) {
			syntaxList.add(Compiler.token);
			lexer.getNextToken();
			newLine();
		} else {
			// do nothing
		}
	}

	public void innerText() throws CompilerException, IOException {
		text();
		innerText();
		if (Compiler.token.equalsIgnoreCase("#START USE")) {
			use();
			innerText();
		}
		if (Compiler.token.equalsIgnoreCase("#NEWLINE")) {
			newLine();
			innerText();
		}
		if (Compiler.token.equalsIgnoreCase("#START AUDIO")) {
			audio();
			innerText();
		}
		if (Compiler.token.equalsIgnoreCase("#START VIDEO")) {
			video();
			innerText();
		} else {
			// do nothing
		}
	}

	public void innerList() throws CompilerException, IOException {
		innerText();
		innerList();
		if (Compiler.token.equalsIgnoreCase("#START BOLD")) {
			bold();
			innerList();
		}
		if (Compiler.token.equalsIgnoreCase("#START ITALICS")) {
			italics();
			innerList();
		}
		if (Compiler.token.equalsIgnoreCase("#START LIST")) {
			list();
			innerList();
		} else {
			// do nothing
		}
	}

	public void text() throws CompilerException, IOException {
		if (!Compiler.token.startsWith("#")) {
			syntaxList.add(Compiler.token);
		} else
			throw new IOException("NOT TEXT!");
	}
}